﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Uco.Models;
using System.Diagnostics;
using System.Net.Mail;
using System.Configuration;
using System.Text;
using System.Reflection;
using System.Globalization;
using System.Web.Configuration;
using Telerik.Web.Mvc.UI;
using System.IO;

namespace Uco.Infrastructure
{
    public static partial class SF
    {

        #region Get/Clean Repository

        public static void CleanMenuRepository()
        {
            HttpContext.Current.Cache.Remove("MenuItems");
        }

        public static List<UcoMenuItem> GetMenuRepository()
        {
            if (HttpContext.Current.Cache["MenuItems"] == null)
            {
                HttpContext.Current.Cache["MenuItems"] = LoadUcoMenuItems().OrderBy(r => r.Order).ToList();
            }
            return (List<UcoMenuItem>)HttpContext.Current.Cache["MenuItems"];
        }

        public static void RefreshMenuRepository()
        {
            List<UcoMenuItem> pages = new List<UcoMenuItem>();


            string PagesPath = HttpContext.Current.Server.MapPath("~/App_Data/pages/");
            if (!Directory.Exists(PagesPath))
            {
                Directory.CreateDirectory(PagesPath);
            }

            string RootPath = HttpContext.Current.Server.MapPath("~");
            string[] AllFiles = Directory.GetFiles(HttpContext.Current.Server.UrlDecode(PagesPath));
            List<string> AllPages = new List<string>();

            for (int i = 0; i < AllFiles.Length; i++)
            {
                AllFiles[i] = AllFiles[i].Replace(RootPath, "");
                AllFiles[i] = AllFiles[i].Replace("\\", "/").ToLower();
                AllFiles[i] = AllFiles[i].Replace("app_data/pages/", "");
                if (AllFiles[i].EndsWith(".xml"))
                {
                    AllPages.Add(AllFiles[i].Replace(".xml", ""));
                }
            }

            List<AbstractPage> apl = new List<AbstractPage>();
            foreach (string item in AllPages)
            {
                AbstractPage aplItem = SF.LoadPage(item);
                if (aplItem != null) apl.Add(SF.LoadPage(item));
            }

            foreach (AbstractPage item in apl)
            {
                pages.Add(new UcoMenuItem()
                {
                    ChangeTime = item.ChangeTime,
                    ID = item.ID,
                    Level = 0,
                    ParentID = (int)item.ParentID,
                    RouteUrl = item.RouteUrl,
                    SeoUrlName = item.SeoUrlName,
                    ShowInMenu = item.ShowInMenu,
                    ShowInSitemap = item.ShowInSitemap,
                    Title = item.Title,
                    Order = item.Order,
                    Visible = item.Visible
                });

            }


            AbstractPage root = LoadPage("root");
            UcoMenuItem rootItem = new UcoMenuItem()
            {
                ChangeTime = root.ChangeTime,
                ID = root.ID,
                Level = 0,
                ParentID = 0,
                RouteUrl = root.RouteUrl,
                SeoUrlName = root.SeoUrlName,
                ShowInMenu = root.ShowInMenu,
                ShowInSitemap = root.ShowInSitemap,
                Title = root.Title,
                Order = root.Order,
                Visible = root.Visible
            };

            SetMenuLevel(rootItem, pages);

            HttpContext.Current.Cache["MenuItems"] = pages.OrderBy(r => r.Order).ToList();
            SF.SaveUcoMenuItems(pages);
        }

        #endregion

        #region Get/Set Repository Items

        public static List<UcoMenuItem> GetMenu(int MaxLevel)
        {
            List<UcoMenuItem> pages = GetMenuRepository();
            pages.RemoveAll(r => r.Level > MaxLevel);
            return pages;
        }

        public static string GetMenuFormated(int MaxLevel)
        {
            List<UcoMenuItem> pages = GetMenuRepository();

            return WriteChildMenu(pages.Where(r => r.Visible == true && r.ShowInMenu == true && r.Level <= MaxLevel).ToList(), null, MaxLevel, 1);
        }

        public static string GetMenuFormated(int MaxLevel, int CurrentPageID)
        {
            List<UcoMenuItem> pages = GetMenuRepository();

            return WriteChildMenu(pages.Where(r => r.Visible == true && r.ShowInMenu == true && r.Level <= MaxLevel).ToList(), null, MaxLevel, 1, CurrentPageID);
        }

        public static string GetSubMenuFormated(int startLevel, int MaxLevel, int MainPageID)
        {
            List<UcoMenuItem> pages = GetMenuRepository();

            UcoMenuItem StartItem = pages.FirstOrDefault(r => r.ID == MainPageID);

            List<int> backWay = new List<int>();
            int backWayLevel = 0;
            do
            {
                backWay.Add(StartItem.ID);
                backWayLevel = backWayLevel + 1;
                StartItem = pages.FirstOrDefault(r => r.ID == StartItem.ParentID);
            }
            while (StartItem != null || backWayLevel > 10);

            try { MainPageID = backWay[backWayLevel - startLevel]; }
            catch { return ""; }
            StartItem = pages.FirstOrDefault(r => r.ID == MainPageID);

            return WriteChildMenu(pages.Where(r => r.Visible == true && r.ShowInMenu == true && r.Level <= MaxLevel).ToList(), StartItem, MaxLevel, startLevel);
        }

        public static string GetSubMenuFormated(int startLevel, int MaxLevel, int MainPageID, int CurentPageID)
        {
            CultureInfo c = System.Threading.Thread.CurrentThread.CurrentCulture;
            string LangCode = c.Name;
            List<UcoMenuItem> pages = GetMenuRepository();

            GlobalizationSection globalization = (GlobalizationSection)ConfigurationManager.GetSection("system.web/globalization");

            UcoMenuItem StartItem = pages.FirstOrDefault(r => r.ID == MainPageID);

            List<int> backWay = new List<int>();
            int backWayLevel = 0;
            do
            {
                backWay.Add(StartItem.ID);
                backWayLevel = backWayLevel + 1;
                StartItem = pages.FirstOrDefault(r => r.ID == StartItem.ParentID);
            }
            while (StartItem != null || backWayLevel > 10);

            try { MainPageID = backWay[backWayLevel - startLevel]; }
            catch { return ""; }
            StartItem = pages.FirstOrDefault(r => r.ID == MainPageID);

            if (globalization.Culture.Trim().ToLower() == LangCode.Trim().ToLower())
            {

                return WriteChildMenu(pages.Where(r => r.Visible == true && r.ShowInMenu == true && r.Level <= MaxLevel).ToList(), StartItem, MaxLevel, startLevel, CurentPageID);
            }
            else
            {
                return WriteChildMenu(pages.Where(r => r.Visible == true && r.ShowInMenu == true && r.Level <= MaxLevel).ToList(), StartItem, MaxLevel, startLevel, CurentPageID);
            }

        }

        public static List<UcoMenuItem> GetSiteMap()
        {
            return GetMenuRepository(); ;
        }

        public static string GetSiteMapFormated()
        {
            List<UcoMenuItem> pages = GetMenuRepository();
            return WriteChildMenu(pages.Where(r => r.Visible == true && r.ShowInSitemap == true).ToList(), null, 10, 1);
        }

        public static string GetMenuUrl(int ID)
        {
			if (ID == 1) return "/";
            List<UcoMenuItem> l = GetMenuRepository();
            UcoMenuItem m = l.FirstOrDefault(r => r.ID == ID);
            if (m != null) return m.Url;
            else return string.Empty;
        }

        public static int GetPageIDByUrl(string Url)
        {
            UcoMenuItem cmi = GetMenuRepository().FirstOrDefault(r => r.Url == "~" + Url);
            if (cmi != null) return cmi.ID;
            else return 0;
        }

        public static string GetSiteMapFormatedXML()
        {
            List<UcoMenuItem> pages = SF.GetMenuRepository();

            CultureInfo c = System.Threading.Thread.CurrentThread.CurrentCulture;
            string LangCode = c.Name;
            GlobalizationSection globalization = (GlobalizationSection)ConfigurationManager.GetSection("system.web/globalization");

            if (globalization.Culture.Trim().ToLower() == LangCode.Trim().ToLower())
            {

                return WriteChildMenuXML(pages.Where(r => r.Visible == true && r.ShowInSitemap == true).ToList());
            }
            else
            {
                return WriteChildMenuXML(pages.Where(r => r.Visible == true && r.ShowInSitemap == true).ToList());
            }
        }
		
        #endregion

        #region Other

        public static string GetSEONameByUrl(string Url)
        {
            if (Url == null) return string.Empty;
            string[] UrlSplit = Url.Split('/');
            if (UrlSplit.Length == 3) return UrlSplit[2];
            else return string.Empty;
        }

        #endregion

        #region Private

        private static string WriteChildMenu(List<UcoMenuItem> pages1, UcoMenuItem Current, int MaxLevel, int CurrentLevel)
        {
            string outStr = "";
            if (pages1.Count(r => r.Level == CurrentLevel && (Current == null ? true : (r.ParentID == Current.ID))) != 0)
            {
                int i = 1;
                outStr = outStr + "<ul class=\"sf-menu\">";
                foreach (UcoMenuItem item in pages1.Where(r => r.Level == CurrentLevel && (Current == null ? true : (r.ParentID == Current.ID))))
                {
                    outStr = outStr + "<li id=\"menu_li_" + CurrentLevel + "_" + i + "\"><a href=\"" + VirtualPathUtility.ToAbsolute(item.Url) + "\">" + item.Title + "</a>";
                    if (MaxLevel != CurrentLevel)
                    {
                        outStr = outStr + WriteChildMenu(pages1, item, MaxLevel, CurrentLevel + 1);
                    }
                    outStr = outStr + "</li>";
                    i = i + 1;
                }
                outStr = outStr + "</ul>";
            }
            return outStr;
        }

        private static string WriteChildMenu(List<UcoMenuItem> pages1, UcoMenuItem Current, int MaxLevel, int CurrentLevel, int CurentPageID)
        {
            string outStr = "";
            if (pages1.Count(r => r.Level == CurrentLevel && (Current == null ? true : (r.ParentID == Current.ID))) != 0)
            {
                int i = 1;
                outStr = outStr + "<ul class=\"sf-menu\">";
                foreach (UcoMenuItem item in pages1.Where(r => r.Level == CurrentLevel && (Current == null ? true : (r.ParentID == Current.ID))))
                {
                    outStr = outStr + "<li id=\"menu_li_" + CurrentLevel + "_" + i + "\"" + (CurentPageID == item.ID ? " class=\"current\"" : "") + (IsParent(item.ID, CurentPageID) ? " class=\"parent\"" : "") + "><a href=\"" + VirtualPathUtility.ToAbsolute(item.Url) + "\">" + item.Title + "</a>";
                    if (MaxLevel != CurrentLevel)
                    {
                        outStr = outStr + WriteChildMenu(pages1, item, MaxLevel, CurrentLevel + 1);
                    }
                    outStr = outStr + "</li>";
                    i = i + 1;
                }
                outStr = outStr + "</ul>";
            }
            return outStr;
        }

        private static string WriteChildMenuXML(List<UcoMenuItem> pages)
        {

            string outStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">";
            foreach (UcoMenuItem item in pages)
            {
                outStr = outStr + System.String.Format("<url><loc>http://{0}{1}</loc><lastmod>{2}</lastmod><changefreq>weekly</changefreq><priority>0</priority></url>", HttpContext.Current.Request.ServerVariables["HTTP_HOST"], VirtualPathUtility.ToAbsolute(item.Url), String.Format("{0:yyyy-MM-dd}", item.ChangeTime));
            }
            outStr = outStr + "</urlset>";

            return outStr;
        }

        private static bool IsParent(int ParentID, int CurrentID)
        {
            int MaxLoop = 5;
            return IsParent(ParentID, CurrentID, MaxLoop);
        }

        private static bool IsParent(int ParentID, int CurrentID, int MaxLoop)
        {
            List<UcoMenuItem> mi = GetMenuRepository();
            UcoMenuItem CurrentItem = mi.FirstOrDefault(r => r.ID == CurrentID);
            UcoMenuItem ParentItem = mi.FirstOrDefault(r => r.ID == ParentID);

            if (CurrentItem == null || ParentItem == null || CurrentItem == ParentItem) return false;
            if (CurrentItem.ParentID == ParentItem.ID)
                return true;

            for (int i = 1; i <= MaxLoop; i++)
            {
                CurrentItem = mi.FirstOrDefault(r => r.ID == CurrentItem.ParentID);

                if (CurrentItem == null || ParentItem == null || CurrentItem == ParentItem) return false;
                if (CurrentItem.ParentID == ParentItem.ID)
                    return true;
            }
            return false;
        }

        private static void SetMenuLevel(UcoMenuItem item1, List<UcoMenuItem> pages)
        {
            foreach (UcoMenuItem item2 in pages.Where(r => r.ParentID == item1.ID).OrderBy(r => r.ID))
            {
                item2.Level = item1.Level + 1;
                SetMenuLevel(item2, pages);
            }
        }

        #endregion
    }
}